<?php
/************************************************************************
 Omnitrix - PHP Development Framework
 Copyright (C) 2012-2018 amonest(eastson@outlook.com)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
************************************************************************/

class admin_controller_backup extends omnitrix_controller
{
	protected $_fp;

	public function index_action()
	{


		$rows = $this->_fetch_backup_list();

		$list_table = otx_html_create_table($this->_('heading_index'), 'table-list');
		$list_table->set_head_cell($this->_('column_name'));
		$list_table->set_head_cell($this->_('column_time'), array('class' => 'center', 'width' => 200));

		if ($rows) {
			foreach ($rows as $row) {
				$list_table->add_body_row();
				$list_table->set_body_cell(otx_html_link(otx_html_strong($row['name']), array('href' => otx_router_url('download', null, null, array('backup_name' => $row['name'])))));
				$list_table->set_body_cell(otx_string_format_size($row['size']), array('class' => 'center'));
				$list_table->set_body_cell(otx_string_format_datetime($row['time']), array('class' => 'center'));
				$list_table->set_body_cell(otx_html_link($this->_('text_delete'), array('href' => otx_router_url('delete', null, null, array('backup_name' => $row['name'])), 'data-confirm' => 'confirm_delete')), array('class' => 'center'));
			};
		} else {
			$list_table->add_body_row();
			$list_table->set_body_cell($this->_('text_no_results'), array('colspan' => 4));
		}

		otx_html_add_navtab($this->_('navtab_index_title'), $this->_('navtab_index_desc', DIR_BACKUP), otx_router_url('index'), true);
		otx_html_add_navtab($this->_('navtab_new_title'), $this->_('navtab_new_desc'), otx_router_url('new'));
		otx_html_add_breadcrumb($this->_('breadcrumb_index'));
		otx_html_response_title($this->_('breadcrumb_index'));
	}

	public function delete_action()
	{
		$backup_name = otx_param_string('backup_name');
		$backup_file = DIR_BACKUP . $backup_name;
		if (file_exists($backup_file)) {
			unlink($backup_file);
		}

		otx_admin_flash_message($this->_('text_success_delete', $backup_name));
		otx_admin_log_action($this->_('text_success_delete', $backup_name));
		otx_router_redirect('index');
	}

	public function download_action()
	{
		$backup_name = otx_param_string('backup_name');

		$backup_file = DIR_BACKUP . $backup_name;
		if (!file_exists($backup_file)) {
			otx_admin_flash_warning($this->_('error_not_exists'));
			otx_router_redirect('index');
		}

		if (substr($backup_name, strlen($backup_name) - strlen('.sql.gz')) == '.sql.gz') {
			header('Content-Encoding: gzip');
			header('Content-Type: application/x-gzip');
			header('Content-Disposition: attachment; filename=' . $backup_name);
			header("Content-length: " . filesize($backup_file));
		} else {
			header('Content-Type: text/x-sql');
			header('Content-Disposition: attachment; filename=' . $backup_name);
			header("Content-length: " . filesize($backup_file));
		}

		echo file_get_contents($backup_file);
		exit;
	}

	public function new_action()
	{
		if (otx_request_is_post()) {
			$selected_tables = otx_param_array('tables');
			$file_format = otx_param_string('file_format');
			$save_type = otx_param_string('save_type');
			$content_type = otx_param_string('content_type');

			if ($selected_tables) {
				@set_time_limit(0);

				$file_name = 'backup.' . $GLOBALS['_XTIMESTAMP'];
				if ($file_format == 'gzip') {
					$file_name = $file_name . '.sql.gz';
				} else {
					$file_name = $file_name . '.sql';
				}

				if ($save_type == 'server') {
					$file_path = DIR_BACKUP . $file_name;
					if ($file_format == 'gzip') {
						$this->_fp = gzopen($file_path, 'w9');
					} else {
						$this->_fp = fopen($file_path, 'w');
					}
				} else {
					if ($file_format == 'gzip') {
						header('Content-Encoding: gzip');
						header('Content-Type: application/x-gzip');
						header('Content-Disposition: attachment; filename=' . $file_name);
					} else {
						header('Content-Type: text/x-sql');
						header('Content-Disposition: attachment; filename=' . $file_name);
					}
				}

				$this->_write_header();

				foreach ($selected_tables as $table_name) {
					if ($content_type == 'both' || $content_type == 'structure') {
						$this->_write_structure($table_name);
					}
					if ($content_type == 'both' || $content_type == 'data') {
						$this->_write_data($table_name);
					}
				}

				if ($save_type == 'server') {
					if ($file_format == 'gzip') {
						gzclose($this->_fp);
					} else {
						fclose($this->_fp);
					}

					otx_admin_flash_message($this->_('text_success_backup'));
					otx_admin_log_action($this->_('text_success_backup'));
					otx_router_redirect('index');
				} else {
					exit;
				}
			}

			otx_admin_flash_warning($this->_('error_tables_empty'));
		} else {
			$file_format = 'gzip';
			$save_type = 'download';
			$content_type = 'both';
		}

		$table_list = array();

		foreach ($GLOBALS['_XDB']->list_tables() as $table_name) {
			$table_list[$table_name] = $table_name;
		}

		$form_wrapper = otx_html_create_wrapper(null, null, $this->_('button_backup'));
		$form_table = $form_wrapper->create_table($this->_('heading_new'), 'table-form');
		$form_table->add_form_entry($this->_('entry_tables'), otx_html_form_select('tables[]', null, array('size' => 15, 'multiple' => 'multiple', 'options' => $table_list)));
		$form_table->add_form_entry($this->_('entry_file_format'), otx_html_form_radiolist('file_format', $file_format, array('label-class' => 'label-radio', 'options' => array('gzip' => $this->_('text_gzip_format'), 'sql' => $this->_('text_sql_format')))));
		$form_table->add_form_entry($this->_('entry_save_type'), otx_html_form_radiolist('save_type', $save_type, array('label-class' => 'label-radio', 'options' => array('server' => $this->_('text_server_file'), 'download' => $this->_('text_download')))));
		$form_table->add_form_entry($this->_('entry_content_type'), otx_html_form_radiolist('content_type', $content_type, array('label-class' => 'label-radio', 'options' => array('both' => $this->_('text_content_both'), 'structure' => $this->_('text_content_structure'), 'data' => $this->_('text_content_data')))));

		otx_html_add_navtab($this->_('navtab_index_title'), $this->_('navtab_index_desc', DIR_BACKUP), otx_router_url('index'));
		otx_html_add_navtab($this->_('navtab_new_title'), $this->_('navtab_new_desc'), otx_router_url('new'), true);
		otx_html_add_breadcrumb($this->_('navtab_new_title'));
		otx_html_response_title($this->_('navtab_new_title'));
	}

	protected function _fetch_backup_list()
	{
		$backup_list = array();
		$backup_files = glob(DIR_BACKUP . 'backup.*');

		if ($backup_files) {
			foreach ($backup_files as $file_name) {
				$base_name = basename(basename($file_name, '.sql'), '.sql.gz');
				$file_time = substr(strrchr($base_name, '.'), 1);
				$backup_list[] = array(
					'name' => basename($file_name),
					'time' => $file_time,
					'size' => filesize($file_name),
					'file' => $file_name
				);
			}
		}

		return $backup_list;
	}

	protected function _flush_buffer($buffer)
	{
		$file_format = otx_param_string('file_format');
		$save_type = otx_param_string('save_type');

		if ($save_type == 'server') {
			if ($file_format == 'gzip') {
				gzwrite($this->_fp, $buffer);
			} else {
				fwrite($this->_fp, $buffer);
			}
		} else {
			if ($file_format == 'gzip') {
				echo gzencode($buffer);
			} else {
				echo $buffer;
			}
		}
	}

	protected function _write_header()
	{
		$sql_data = "#\n";
		$sql_data .= "# Omnitrix Backup Script\n";
		$sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $GLOBALS['_XTIMESTAMP']) . " GMT\n";
		$sql_data .= "#\n\n";
		$this->_flush_buffer($sql_data);;
	}

	protected function _write_structure($table_name)
	{
		$sql = 'SHOW CREATE TABLE ' . otx_db_escape_identifier($table_name);
		$row = otx_db_fetch_row($sql);

		$sql_data = "#\n";
		$sql_data .= "# Structure for table $table_name \n";
		$sql_data .= "#\n";
		$sql_data .= "DROP TABLE IF EXISTS " . otx_db_escape_identifier($table_name) . ";\n";
		$this->_flush_buffer($sql_data . $row['Create Table'] . ";\n\n");
	}

	protected function _write_data($table_name)
	{
		$sql_data = "#\n";
		$sql_data .= "# Data for table $table_name \n";
		$sql_data .= "#\n";
		$this->_flush_buffer($sql_data);

		$sql = 'SHOW FIELDS FROM ' . otx_db_escape_identifier($table_name);
		$field_rows = otx_db_fetch_all($sql);

		$fields = array();
		foreach ($field_rows as $row) {
			$fields[$row['Field']] = otx_db_escape_identifier($row['Field']);
		}

		$sql = 'SELECT * FROM ' . otx_db_escape_identifier($table_name);
		$data_rows = otx_db_fetch_all($sql);
		foreach ((array) $data_rows as $row) {
			$values = array();

			foreach (array_keys($fields) as $field_name) {
				$values[] = otx_db_escape_value($row[$field_name]);
			}

			$sql_data = 'INSERT INTO ' . otx_db_escape_identifier($table_name)
					. '(' . implode(', ', array_values($fields)) . ')'
					. ' VALUES (' . implode(', ', $values) . ');';
			$this->_flush_buffer($sql_data . "\n");
		}

		$this->_flush_buffer("\n");
	}
}